home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / urllib2.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  35KB  |  1,174 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. import base64
  5. import hashlib
  6. import httplib
  7. import mimetools
  8. import os
  9. import posixpath
  10. import random
  11. import re
  12. import socket
  13. import sys
  14. import time
  15. import urlparse
  16. import bisect
  17.  
  18. try:
  19.     from cStringIO import StringIO
  20. except ImportError:
  21.     from StringIO import StringIO
  22.  
  23. from urllib import unwrap, unquote, splittype, splithost, quote, addinfourl, splitport, splitgophertype, splitquery, splitattr, ftpwrapper, noheaders, splituser, splitpasswd, splitvalue
  24. from urllib import localhost, url2pathname, getproxies
  25. __version__ = sys.version[:3]
  26. _opener = None
  27.  
  28. def urlopen(url, data = None):
  29.     global _opener
  30.     if _opener is None:
  31.         _opener = build_opener()
  32.     
  33.     return _opener.open(url, data)
  34.  
  35.  
  36. def install_opener(opener):
  37.     global _opener
  38.     _opener = opener
  39.  
  40.  
  41. class URLError(IOError):
  42.     
  43.     def __init__(self, reason):
  44.         self.args = (reason,)
  45.         self.reason = reason
  46.  
  47.     
  48.     def __str__(self):
  49.         return '<urlopen error %s>' % self.reason
  50.  
  51.  
  52.  
  53. class HTTPError(URLError, addinfourl):
  54.     __super_init = addinfourl.__init__
  55.     
  56.     def __init__(self, url, code, msg, hdrs, fp):
  57.         self.code = code
  58.         self.msg = msg
  59.         self.hdrs = hdrs
  60.         self.fp = fp
  61.         self.filename = url
  62.         if fp is not None:
  63.             self._HTTPError__super_init(fp, hdrs, url)
  64.         
  65.  
  66.     
  67.     def __str__(self):
  68.         return 'HTTP Error %s: %s' % (self.code, self.msg)
  69.  
  70.  
  71.  
  72. class GopherError(URLError):
  73.     pass
  74.  
  75. _cut_port_re = re.compile(':\\d+$')
  76.  
  77. def request_host(request):
  78.     url = request.get_full_url()
  79.     host = urlparse.urlparse(url)[1]
  80.     if host == '':
  81.         host = request.get_header('Host', '')
  82.     
  83.     host = _cut_port_re.sub('', host, 1)
  84.     return host.lower()
  85.  
  86.  
  87. class Request:
  88.     
  89.     def __init__(self, url, data = None, headers = { }, origin_req_host = None, unverifiable = False):
  90.         self._Request__original = unwrap(url)
  91.         self.type = None
  92.         self.host = None
  93.         self.port = None
  94.         self.data = data
  95.         self.headers = { }
  96.         for key, value in headers.items():
  97.             self.add_header(key, value)
  98.         
  99.         self.unredirected_hdrs = { }
  100.         if origin_req_host is None:
  101.             origin_req_host = request_host(self)
  102.         
  103.         self.origin_req_host = origin_req_host
  104.         self.unverifiable = unverifiable
  105.  
  106.     
  107.     def __getattr__(self, attr):
  108.         if attr[:12] == '_Request__r_':
  109.             name = attr[12:]
  110.             if hasattr(Request, 'get_' + name):
  111.                 getattr(self, 'get_' + name)()
  112.                 return getattr(self, attr)
  113.             
  114.         
  115.         raise AttributeError, attr
  116.  
  117.     
  118.     def get_method(self):
  119.         if self.has_data():
  120.             return 'POST'
  121.         else:
  122.             return 'GET'
  123.  
  124.     
  125.     def add_data(self, data):
  126.         self.data = data
  127.  
  128.     
  129.     def has_data(self):
  130.         return self.data is not None
  131.  
  132.     
  133.     def get_data(self):
  134.         return self.data
  135.  
  136.     
  137.     def get_full_url(self):
  138.         return self._Request__original
  139.  
  140.     
  141.     def get_type(self):
  142.         if self.type is None:
  143.             (self.type, self._Request__r_type) = splittype(self._Request__original)
  144.             if self.type is None:
  145.                 raise ValueError, 'unknown url type: %s' % self._Request__original
  146.             
  147.         
  148.         return self.type
  149.  
  150.     
  151.     def get_host(self):
  152.         if self.host is None:
  153.             (self.host, self._Request__r_host) = splithost(self._Request__r_type)
  154.             if self.host:
  155.                 self.host = unquote(self.host)
  156.             
  157.         
  158.         return self.host
  159.  
  160.     
  161.     def get_selector(self):
  162.         return self._Request__r_host
  163.  
  164.     
  165.     def set_proxy(self, host, type):
  166.         self.host = host
  167.         self.type = type
  168.         self._Request__r_host = self._Request__original
  169.  
  170.     
  171.     def get_origin_req_host(self):
  172.         return self.origin_req_host
  173.  
  174.     
  175.     def is_unverifiable(self):
  176.         return self.unverifiable
  177.  
  178.     
  179.     def add_header(self, key, val):
  180.         self.headers[key.capitalize()] = val
  181.  
  182.     
  183.     def add_unredirected_header(self, key, val):
  184.         self.unredirected_hdrs[key.capitalize()] = val
  185.  
  186.     
  187.     def has_header(self, header_name):
  188.         if not header_name in self.headers:
  189.             pass
  190.         return header_name in self.unredirected_hdrs
  191.  
  192.     
  193.     def get_header(self, header_name, default = None):
  194.         return self.headers.get(header_name, self.unredirected_hdrs.get(header_name, default))
  195.  
  196.     
  197.     def header_items(self):
  198.         hdrs = self.unredirected_hdrs.copy()
  199.         hdrs.update(self.headers)
  200.         return hdrs.items()
  201.  
  202.  
  203.  
  204. class OpenerDirector:
  205.     
  206.     def __init__(self):
  207.         client_version = 'Python-urllib/%s' % __version__
  208.         self.addheaders = [
  209.             ('User-agent', client_version)]
  210.         self.handlers = []
  211.         self.handle_open = { }
  212.         self.handle_error = { }
  213.         self.process_response = { }
  214.         self.process_request = { }
  215.  
  216.     
  217.     def add_handler(self, handler):
  218.         if not hasattr(handler, 'add_parent'):
  219.             raise TypeError('expected BaseHandler instance, got %r' % type(handler))
  220.         
  221.         added = False
  222.         for meth in dir(handler):
  223.             if meth in ('redirect_request', 'do_open', 'proxy_open'):
  224.                 continue
  225.             
  226.             i = meth.find('_')
  227.             protocol = meth[:i]
  228.             condition = meth[i + 1:]
  229.             if condition.startswith('error'):
  230.                 j = condition.find('_') + i + 1
  231.                 kind = meth[j + 1:]
  232.                 
  233.                 try:
  234.                     kind = int(kind)
  235.                 except ValueError:
  236.                     pass
  237.  
  238.                 lookup = self.handle_error.get(protocol, { })
  239.                 self.handle_error[protocol] = lookup
  240.             elif condition == 'open':
  241.                 kind = protocol
  242.                 lookup = self.handle_open
  243.             elif condition == 'response':
  244.                 kind = protocol
  245.                 lookup = self.process_response
  246.             elif condition == 'request':
  247.                 kind = protocol
  248.                 lookup = self.process_request
  249.             
  250.             handlers = lookup.setdefault(kind, [])
  251.             if handlers:
  252.                 bisect.insort(handlers, handler)
  253.             else:
  254.                 handlers.append(handler)
  255.             added = True
  256.         
  257.         if added:
  258.             bisect.insort(self.handlers, handler)
  259.             handler.add_parent(self)
  260.         
  261.  
  262.     
  263.     def close(self):
  264.         pass
  265.  
  266.     
  267.     def _call_chain(self, chain, kind, meth_name, *args):
  268.         handlers = chain.get(kind, ())
  269.         for handler in handlers:
  270.             func = getattr(handler, meth_name)
  271.             result = func(*args)
  272.             if result is not None:
  273.                 return result
  274.                 continue
  275.         
  276.  
  277.     
  278.     def open(self, fullurl, data = None):
  279.         if isinstance(fullurl, basestring):
  280.             req = Request(fullurl, data)
  281.         else:
  282.             req = fullurl
  283.             if data is not None:
  284.                 req.add_data(data)
  285.             
  286.         protocol = req.get_type()
  287.         meth_name = protocol + '_request'
  288.         for processor in self.process_request.get(protocol, []):
  289.             meth = getattr(processor, meth_name)
  290.             req = meth(req)
  291.         
  292.         response = self._open(req, data)
  293.         meth_name = protocol + '_response'
  294.         for processor in self.process_response.get(protocol, []):
  295.             meth = getattr(processor, meth_name)
  296.             response = meth(req, response)
  297.         
  298.         return response
  299.  
  300.     
  301.     def _open(self, req, data = None):
  302.         result = self._call_chain(self.handle_open, 'default', 'default_open', req)
  303.         if result:
  304.             return result
  305.         
  306.         protocol = req.get_type()
  307.         result = self._call_chain(self.handle_open, protocol, protocol + '_open', req)
  308.         if result:
  309.             return result
  310.         
  311.         return self._call_chain(self.handle_open, 'unknown', 'unknown_open', req)
  312.  
  313.     
  314.     def error(self, proto, *args):
  315.         if proto in ('http', 'https'):
  316.             dict = self.handle_error['http']
  317.             proto = args[2]
  318.             meth_name = 'http_error_%s' % proto
  319.             http_err = 1
  320.             orig_args = args
  321.         else:
  322.             dict = self.handle_error
  323.             meth_name = proto + '_error'
  324.             http_err = 0
  325.         args = (dict, proto, meth_name) + args
  326.         result = self._call_chain(*args)
  327.         if result:
  328.             return result
  329.         
  330.         if http_err:
  331.             args = (dict, 'default', 'http_error_default') + orig_args
  332.             return self._call_chain(*args)
  333.         
  334.  
  335.  
  336.  
  337. def build_opener(*handlers):
  338.     import types
  339.     
  340.     def isclass(obj):
  341.         if not isinstance(obj, types.ClassType):
  342.             pass
  343.         return hasattr(obj, '__bases__')
  344.  
  345.     opener = OpenerDirector()
  346.     default_classes = [
  347.         ProxyHandler,
  348.         UnknownHandler,
  349.         HTTPHandler,
  350.         HTTPDefaultErrorHandler,
  351.         HTTPRedirectHandler,
  352.         FTPHandler,
  353.         FileHandler,
  354.         HTTPErrorProcessor]
  355.     if hasattr(httplib, 'HTTPS'):
  356.         default_classes.append(HTTPSHandler)
  357.     
  358.     skip = set()
  359.     for klass in default_classes:
  360.         for check in handlers:
  361.             if isclass(check):
  362.                 if issubclass(check, klass):
  363.                     skip.add(klass)
  364.                 
  365.             issubclass(check, klass)
  366.             if isinstance(check, klass):
  367.                 skip.add(klass)
  368.                 continue
  369.         
  370.     
  371.     for klass in skip:
  372.         default_classes.remove(klass)
  373.     
  374.     for klass in default_classes:
  375.         opener.add_handler(klass())
  376.     
  377.     for h in handlers:
  378.         if isclass(h):
  379.             h = h()
  380.         
  381.         opener.add_handler(h)
  382.     
  383.     return opener
  384.  
  385.  
  386. class BaseHandler:
  387.     handler_order = 500
  388.     
  389.     def add_parent(self, parent):
  390.         self.parent = parent
  391.  
  392.     
  393.     def close(self):
  394.         pass
  395.  
  396.     
  397.     def __lt__(self, other):
  398.         if not hasattr(other, 'handler_order'):
  399.             return True
  400.         
  401.         return self.handler_order < other.handler_order
  402.  
  403.  
  404.  
  405. class HTTPErrorProcessor(BaseHandler):
  406.     handler_order = 1000
  407.     
  408.     def http_response(self, request, response):
  409.         code = response.code
  410.         msg = response.msg
  411.         hdrs = response.info()
  412.         if code not in (200, 206):
  413.             response = self.parent.error('http', request, response, code, msg, hdrs)
  414.         
  415.         return response
  416.  
  417.     https_response = http_response
  418.  
  419.  
  420. class HTTPDefaultErrorHandler(BaseHandler):
  421.     
  422.     def http_error_default(self, req, fp, code, msg, hdrs):
  423.         raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
  424.  
  425.  
  426.  
  427. class HTTPRedirectHandler(BaseHandler):
  428.     max_repeats = 4
  429.     max_redirections = 10
  430.     
  431.     def redirect_request(self, req, fp, code, msg, headers, newurl):
  432.         m = req.get_method()
  433.         if (code in (301, 302, 303, 307) or m in ('GET', 'HEAD') or code in (301, 302, 303)) and m == 'POST':
  434.             newurl = newurl.replace(' ', '%20')
  435.             return Request(newurl, headers = req.headers, origin_req_host = req.get_origin_req_host(), unverifiable = True)
  436.         else:
  437.             raise HTTPError(req.get_full_url(), code, msg, headers, fp)
  438.  
  439.     
  440.     def http_error_302(self, req, fp, code, msg, headers):
  441.         if 'location' in headers:
  442.             newurl = headers.getheaders('location')[0]
  443.         elif 'uri' in headers:
  444.             newurl = headers.getheaders('uri')[0]
  445.         else:
  446.             return None
  447.         newurl = urlparse.urljoin(req.get_full_url(), newurl)
  448.         new = self.redirect_request(req, fp, code, msg, headers, newurl)
  449.         if new is None:
  450.             return None
  451.         
  452.         if hasattr(req, 'redirect_dict'):
  453.             visited = new.redirect_dict = req.redirect_dict
  454.             if visited.get(newurl, 0) >= self.max_repeats or len(visited) >= self.max_redirections:
  455.                 raise HTTPError(req.get_full_url(), code, self.inf_msg + msg, headers, fp)
  456.             
  457.         else:
  458.             visited = new.redirect_dict = req.redirect_dict = { }
  459.         visited[newurl] = visited.get(newurl, 0) + 1
  460.         fp.read()
  461.         fp.close()
  462.         return self.parent.open(new)
  463.  
  464.     http_error_301 = http_error_303 = http_error_307 = http_error_302
  465.     inf_msg = 'The HTTP server returned a redirect error that would lead to an infinite loop.\nThe last 30x error message was:\n'
  466.  
  467.  
  468. def _parse_proxy(proxy):
  469.     (scheme, r_scheme) = splittype(proxy)
  470.     if not r_scheme.startswith('/'):
  471.         scheme = None
  472.         authority = proxy
  473.     elif not r_scheme.startswith('//'):
  474.         raise ValueError('proxy URL with no authority: %r' % proxy)
  475.     
  476.     end = r_scheme.find('/', 2)
  477.     if end == -1:
  478.         end = None
  479.     
  480.     authority = r_scheme[2:end]
  481.     (userinfo, hostport) = splituser(authority)
  482.     if userinfo is not None:
  483.         (user, password) = splitpasswd(userinfo)
  484.     else:
  485.         user = None
  486.         password = None
  487.     return (scheme, user, password, hostport)
  488.  
  489.  
  490. class ProxyHandler(BaseHandler):
  491.     handler_order = 100
  492.     
  493.     def __init__(self, proxies = None):
  494.         if proxies is None:
  495.             proxies = getproxies()
  496.         
  497.         self.proxies = proxies
  498.         for type, url in proxies.items():
  499.             setattr(self, '%s_open' % type, (lambda r, proxy = url, type = type, meth = self.proxy_open: meth(r, proxy, type)))
  500.         
  501.  
  502.     
  503.     def proxy_open(self, req, proxy, type):
  504.         orig_type = req.get_type()
  505.         (proxy_type, user, password, hostport) = _parse_proxy(proxy)
  506.         if proxy_type is None:
  507.             proxy_type = orig_type
  508.         
  509.         if user and password:
  510.             user_pass = '%s:%s' % (unquote(user), unquote(password))
  511.             creds = base64.b64encode(user_pass).strip()
  512.             req.add_header('Proxy-authorization', 'Basic ' + creds)
  513.         
  514.         hostport = unquote(hostport)
  515.         req.set_proxy(hostport, proxy_type)
  516.         if orig_type == proxy_type:
  517.             return None
  518.         else:
  519.             return self.parent.open(req)
  520.  
  521.  
  522.  
  523. class HTTPPasswordMgr:
  524.     
  525.     def __init__(self):
  526.         self.passwd = { }
  527.  
  528.     
  529.     def add_password(self, realm, uri, user, passwd):
  530.         if isinstance(uri, basestring):
  531.             uri = [
  532.                 uri]
  533.         
  534.         if realm not in self.passwd:
  535.             self.passwd[realm] = { }
  536.         
  537.         for default_port in (True, False):
  538.             reduced_uri = []([ self.reduce_uri(u, default_port) for u in uri ])
  539.             self.passwd[realm][reduced_uri] = (user, passwd)
  540.         
  541.  
  542.     
  543.     def find_user_password(self, realm, authuri):
  544.         domains = self.passwd.get(realm, { })
  545.         for default_port in (True, False):
  546.             reduced_authuri = self.reduce_uri(authuri, default_port)
  547.             for uris, authinfo in domains.iteritems():
  548.                 for uri in uris:
  549.                     if self.is_suburi(uri, reduced_authuri):
  550.                         return authinfo
  551.                         continue
  552.                 
  553.             
  554.         
  555.         return (None, None)
  556.  
  557.     
  558.     def reduce_uri(self, uri, default_port = True):
  559.         parts = urlparse.urlsplit(uri)
  560.         if parts[1]:
  561.             scheme = parts[0]
  562.             authority = parts[1]
  563.             if not parts[2]:
  564.                 pass
  565.             path = '/'
  566.         else:
  567.             scheme = None
  568.             authority = uri
  569.             path = '/'
  570.         (host, port) = splitport(authority)
  571.         if default_port and port is None and scheme is not None:
  572.             dport = {
  573.                 'http': 80,
  574.                 'https': 443 }.get(scheme)
  575.             if dport is not None:
  576.                 authority = '%s:%d' % (host, dport)
  577.             
  578.         
  579.         return (authority, path)
  580.  
  581.     
  582.     def is_suburi(self, base, test):
  583.         if base == test:
  584.             return True
  585.         
  586.         if base[0] != test[0]:
  587.             return False
  588.         
  589.         common = posixpath.commonprefix((base[1], test[1]))
  590.         if len(common) == len(base[1]):
  591.             return True
  592.         
  593.         return False
  594.  
  595.  
  596.  
  597. class HTTPPasswordMgrWithDefaultRealm(HTTPPasswordMgr):
  598.     
  599.     def find_user_password(self, realm, authuri):
  600.         (user, password) = HTTPPasswordMgr.find_user_password(self, realm, authuri)
  601.         if user is not None:
  602.             return (user, password)
  603.         
  604.         return HTTPPasswordMgr.find_user_password(self, None, authuri)
  605.  
  606.  
  607.  
  608. class AbstractBasicAuthHandler:
  609.     rx = re.compile('(?:.*,)*[ \t]*([^ \t]+)[ \t]+realm="([^"]*)"', re.I)
  610.     
  611.     def __init__(self, password_mgr = None):
  612.         if password_mgr is None:
  613.             password_mgr = HTTPPasswordMgr()
  614.         
  615.         self.passwd = password_mgr
  616.         self.add_password = self.passwd.add_password
  617.  
  618.     
  619.     def http_error_auth_reqed(self, authreq, host, req, headers):
  620.         authreq = headers.get(authreq, None)
  621.         if authreq:
  622.             mo = AbstractBasicAuthHandler.rx.search(authreq)
  623.             if mo:
  624.                 (scheme, realm) = mo.groups()
  625.                 if scheme.lower() == 'basic':
  626.                     return self.retry_http_basic_auth(host, req, realm)
  627.                 
  628.             
  629.         
  630.  
  631.     
  632.     def retry_http_basic_auth(self, host, req, realm):
  633.         (user, pw) = self.passwd.find_user_password(realm, host)
  634.         if pw is not None:
  635.             raw = '%s:%s' % (user, pw)
  636.             auth = 'Basic %s' % base64.b64encode(raw).strip()
  637.             if req.headers.get(self.auth_header, None) == auth:
  638.                 return None
  639.             
  640.             req.add_header(self.auth_header, auth)
  641.             return self.parent.open(req)
  642.         else:
  643.             return None
  644.  
  645.  
  646.  
  647. class HTTPBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
  648.     auth_header = 'Authorization'
  649.     
  650.     def http_error_401(self, req, fp, code, msg, headers):
  651.         url = req.get_full_url()
  652.         return self.http_error_auth_reqed('www-authenticate', url, req, headers)
  653.  
  654.  
  655.  
  656. class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
  657.     auth_header = 'Proxy-authorization'
  658.     
  659.     def http_error_407(self, req, fp, code, msg, headers):
  660.         authority = req.get_host()
  661.         return self.http_error_auth_reqed('proxy-authenticate', authority, req, headers)
  662.  
  663.  
  664.  
  665. def randombytes(n):
  666.     pass
  667.  
  668.  
  669. class AbstractDigestAuthHandler:
  670.     
  671.     def __init__(self, passwd = None):
  672.         if passwd is None:
  673.             passwd = HTTPPasswordMgr()
  674.         
  675.         self.passwd = passwd
  676.         self.add_password = self.passwd.add_password
  677.         self.retried = 0
  678.         self.nonce_count = 0
  679.  
  680.     
  681.     def reset_retry_count(self):
  682.         self.retried = 0
  683.  
  684.     
  685.     def http_error_auth_reqed(self, auth_header, host, req, headers):
  686.         authreq = headers.get(auth_header, None)
  687.         if authreq:
  688.             scheme = authreq.split()[0]
  689.             if scheme.lower() == 'digest':
  690.                 return self.retry_http_digest_auth(req, authreq)
  691.             
  692.         
  693.  
  694.     
  695.     def retry_http_digest_auth(self, req, auth):
  696.         (token, challenge) = auth.split(' ', 1)
  697.         chal = parse_keqv_list(parse_http_list(challenge))
  698.         auth = self.get_authorization(req, chal)
  699.         if auth:
  700.             auth_val = 'Digest %s' % auth
  701.             if req.headers.get(self.auth_header, None) == auth_val:
  702.                 return None
  703.             
  704.             req.add_unredirected_header(self.auth_header, auth_val)
  705.             resp = self.parent.open(req)
  706.             return resp
  707.         
  708.  
  709.     
  710.     def get_cnonce(self, nonce):
  711.         dig = hashlib.sha1('%s:%s:%s:%s' % (self.nonce_count, nonce, time.ctime(), randombytes(8))).hexdigest()
  712.         return dig[:16]
  713.  
  714.     
  715.     def get_authorization(self, req, chal):
  716.         
  717.         try:
  718.             realm = chal['realm']
  719.             nonce = chal['nonce']
  720.             qop = chal.get('qop')
  721.             algorithm = chal.get('algorithm', 'MD5')
  722.             opaque = chal.get('opaque', None)
  723.         except KeyError:
  724.             return None
  725.  
  726.         (H, KD) = self.get_algorithm_impls(algorithm)
  727.         if H is None:
  728.             return None
  729.         
  730.         (user, pw) = self.passwd.find_user_password(realm, req.get_full_url())
  731.         if user is None:
  732.             return None
  733.         
  734.         if req.has_data():
  735.             entdig = self.get_entity_digest(req.get_data(), chal)
  736.         else:
  737.             entdig = None
  738.         A1 = '%s:%s:%s' % (user, realm, pw)
  739.         A2 = '%s:%s' % (req.get_method(), req.get_selector())
  740.         if qop == 'auth':
  741.             self.nonce_count += 1
  742.             ncvalue = '%08x' % self.nonce_count
  743.             cnonce = self.get_cnonce(nonce)
  744.             noncebit = '%s:%s:%s:%s:%s' % (nonce, ncvalue, cnonce, qop, H(A2))
  745.             respdig = KD(H(A1), noncebit)
  746.         elif qop is None:
  747.             respdig = KD(H(A1), '%s:%s' % (nonce, H(A2)))
  748.         else:
  749.             raise URLError("qop '%s' is not supported." % qop)
  750.         base = 'username="%s", realm="%s", nonce="%s", uri="%s", response="%s"' % (user, realm, nonce, req.get_selector(), respdig)
  751.         if opaque:
  752.             base += ', opaque="%s"' % opaque
  753.         
  754.         if entdig:
  755.             base += ', digest="%s"' % entdig
  756.         
  757.         base += ', algorithm="%s"' % algorithm
  758.         if qop:
  759.             base += ', qop=auth, nc=%s, cnonce="%s"' % (ncvalue, cnonce)
  760.         
  761.         return base
  762.  
  763.     
  764.     def get_algorithm_impls(self, algorithm):
  765.         if algorithm == 'MD5':
  766.             
  767.             H = lambda x: hashlib.md5(x).hexdigest()
  768.         elif algorithm == 'SHA':
  769.             
  770.             H = lambda x: hashlib.sha1(x).hexdigest()
  771.         
  772.         
  773.         KD = lambda s, d: H('%s:%s' % (s, d))
  774.         return (H, KD)
  775.  
  776.     
  777.     def get_entity_digest(self, data, chal):
  778.         pass
  779.  
  780.  
  781.  
  782. class HTTPDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler):
  783.     auth_header = 'Authorization'
  784.     handler_order = 490
  785.     
  786.     def http_error_401(self, req, fp, code, msg, headers):
  787.         host = urlparse.urlparse(req.get_full_url())[1]
  788.         retry = self.http_error_auth_reqed('www-authenticate', host, req, headers)
  789.         self.reset_retry_count()
  790.         return retry
  791.  
  792.  
  793.  
  794. class ProxyDigestAuthHandler(BaseHandler, AbstractDigestAuthHandler):
  795.     auth_header = 'Proxy-Authorization'
  796.     handler_order = 490
  797.     
  798.     def http_error_407(self, req, fp, code, msg, headers):
  799.         host = req.get_host()
  800.         retry = self.http_error_auth_reqed('proxy-authenticate', host, req, headers)
  801.         self.reset_retry_count()
  802.         return retry
  803.  
  804.  
  805.  
  806. class AbstractHTTPHandler(BaseHandler):
  807.     
  808.     def __init__(self, debuglevel = 0):
  809.         self._debuglevel = debuglevel
  810.  
  811.     
  812.     def set_http_debuglevel(self, level):
  813.         self._debuglevel = level
  814.  
  815.     
  816.     def do_request_(self, request):
  817.         host = request.get_host()
  818.         if not host:
  819.             raise URLError('no host given')
  820.         
  821.         if request.has_data():
  822.             data = request.get_data()
  823.             if not request.has_header('Content-type'):
  824.                 request.add_unredirected_header('Content-type', 'application/x-www-form-urlencoded')
  825.             
  826.             if not request.has_header('Content-length'):
  827.                 request.add_unredirected_header('Content-length', '%d' % len(data))
  828.             
  829.         
  830.         (scheme, sel) = splittype(request.get_selector())
  831.         (sel_host, sel_path) = splithost(sel)
  832.         if not request.has_header('Host'):
  833.             if not sel_host:
  834.                 pass
  835.             request.add_unredirected_header('Host', host)
  836.         
  837.         for name, value in self.parent.addheaders:
  838.             name = name.capitalize()
  839.             if not request.has_header(name):
  840.                 request.add_unredirected_header(name, value)
  841.                 continue
  842.         
  843.         return request
  844.  
  845.     
  846.     def do_open(self, http_class, req):
  847.         host = req.get_host()
  848.         if not host:
  849.             raise URLError('no host given')
  850.         
  851.         h = http_class(host)
  852.         h.set_debuglevel(self._debuglevel)
  853.         headers = dict(req.headers)
  854.         headers.update(req.unredirected_hdrs)
  855.         headers['Connection'] = 'close'
  856.         headers = dict((lambda .0: for name, val in .0:
  857. (name.title(), val))(headers.items()))
  858.         
  859.         try:
  860.             h.request(req.get_method(), req.get_selector(), req.data, headers)
  861.             r = h.getresponse()
  862.         except socket.error:
  863.             err = None
  864.             raise URLError(err)
  865.  
  866.         r.recv = r.read
  867.         fp = socket._fileobject(r, close = True)
  868.         resp = addinfourl(fp, r.msg, req.get_full_url())
  869.         resp.code = r.status
  870.         resp.msg = r.reason
  871.         return resp
  872.  
  873.  
  874.  
  875. class HTTPHandler(AbstractHTTPHandler):
  876.     
  877.     def http_open(self, req):
  878.         return self.do_open(httplib.HTTPConnection, req)
  879.  
  880.     http_request = AbstractHTTPHandler.do_request_
  881.  
  882. if hasattr(httplib, 'HTTPS'):
  883.     
  884.     class HTTPSHandler(AbstractHTTPHandler):
  885.         
  886.         def https_open(self, req):
  887.             return self.do_open(httplib.HTTPSConnection, req)
  888.  
  889.         https_request = AbstractHTTPHandler.do_request_
  890.  
  891.  
  892.  
  893. class HTTPCookieProcessor(BaseHandler):
  894.     
  895.     def __init__(self, cookiejar = None):
  896.         import cookielib as cookielib
  897.         if cookiejar is None:
  898.             cookiejar = cookielib.CookieJar()
  899.         
  900.         self.cookiejar = cookiejar
  901.  
  902.     
  903.     def http_request(self, request):
  904.         self.cookiejar.add_cookie_header(request)
  905.         return request
  906.  
  907.     
  908.     def http_response(self, request, response):
  909.         self.cookiejar.extract_cookies(response, request)
  910.         return response
  911.  
  912.     https_request = http_request
  913.     https_response = http_response
  914.  
  915.  
  916. class UnknownHandler(BaseHandler):
  917.     
  918.     def unknown_open(self, req):
  919.         type = req.get_type()
  920.         raise URLError('unknown url type: %s' % type)
  921.  
  922.  
  923.  
  924. def parse_keqv_list(l):
  925.     parsed = { }
  926.     for elt in l:
  927.         (k, v) = elt.split('=', 1)
  928.         if v[0] == '"' and v[-1] == '"':
  929.             v = v[1:-1]
  930.         
  931.         parsed[k] = v
  932.     
  933.     return parsed
  934.  
  935.  
  936. def parse_http_list(s):
  937.     res = []
  938.     part = ''
  939.     escape = quote = False
  940.     for cur in s:
  941.         if escape:
  942.             part += cur
  943.             escape = False
  944.             continue
  945.         
  946.         if quote:
  947.             if cur == '\\':
  948.                 escape = True
  949.                 continue
  950.             elif cur == '"':
  951.                 quote = False
  952.             
  953.             part += cur
  954.             continue
  955.         
  956.         if cur == ',':
  957.             res.append(part)
  958.             part = ''
  959.             continue
  960.         
  961.         if cur == '"':
  962.             quote = True
  963.         
  964.         part += cur
  965.     
  966.     if part:
  967.         res.append(part)
  968.     
  969.     return [ part.strip() for part in res ]
  970.  
  971.  
  972. class FileHandler(BaseHandler):
  973.     
  974.     def file_open(self, req):
  975.         url = req.get_selector()
  976.         if url[:2] == '//' and url[2:3] != '/':
  977.             req.type = 'ftp'
  978.             return self.parent.open(req)
  979.         else:
  980.             return self.open_local_file(req)
  981.  
  982.     names = None
  983.     
  984.     def get_names(self):
  985.         if FileHandler.names is None:
  986.             
  987.             try:
  988.                 FileHandler.names = (socket.gethostbyname('localhost'), socket.gethostbyname(socket.gethostname()))
  989.             except socket.gaierror:
  990.                 FileHandler.names = (socket.gethostbyname('localhost'),)
  991.             except:
  992.                 None<EXCEPTION MATCH>socket.gaierror
  993.             
  994.  
  995.         None<EXCEPTION MATCH>socket.gaierror
  996.         return FileHandler.names
  997.  
  998.     
  999.     def open_local_file(self, req):
  1000.         import email.Utils as email
  1001.         import mimetypes as mimetypes
  1002.         host = req.get_host()
  1003.         file = req.get_selector()
  1004.         localfile = url2pathname(file)
  1005.         stats = os.stat(localfile)
  1006.         size = stats.st_size
  1007.         modified = email.Utils.formatdate(stats.st_mtime, usegmt = True)
  1008.         mtype = mimetypes.guess_type(file)[0]
  1009.         if not mtype:
  1010.             pass
  1011.         headers = mimetools.Message(StringIO('Content-type: %s\nContent-length: %d\nLast-modified: %s\n' % ('text/plain', size, modified)))
  1012.         if host:
  1013.             (host, port) = splitport(host)
  1014.         
  1015.         if (not host or not port) and socket.gethostbyname(host) in self.get_names():
  1016.             return addinfourl(open(localfile, 'rb'), headers, 'file:' + file)
  1017.         
  1018.         raise URLError('file not on local host')
  1019.  
  1020.  
  1021.  
  1022. class FTPHandler(BaseHandler):
  1023.     
  1024.     def ftp_open(self, req):
  1025.         import ftplib as ftplib
  1026.         import mimetypes
  1027.         host = req.get_host()
  1028.         if not host:
  1029.             raise IOError, ('ftp error', 'no host given')
  1030.         
  1031.         (host, port) = splitport(host)
  1032.         if port is None:
  1033.             port = ftplib.FTP_PORT
  1034.         else:
  1035.             port = int(port)
  1036.         (user, host) = splituser(host)
  1037.         if user:
  1038.             (user, passwd) = splitpasswd(user)
  1039.         else:
  1040.             passwd = None
  1041.         host = unquote(host)
  1042.         if not user:
  1043.             pass
  1044.         user = unquote('')
  1045.         if not passwd:
  1046.             pass
  1047.         passwd = unquote('')
  1048.         
  1049.         try:
  1050.             host = socket.gethostbyname(host)
  1051.         except socket.error:
  1052.             msg = None
  1053.             raise URLError(msg)
  1054.  
  1055.         (path, attrs) = splitattr(req.get_selector())
  1056.         dirs = path.split('/')
  1057.         dirs = map(unquote, dirs)
  1058.         dirs = dirs[:-1]
  1059.         file = dirs[-1]
  1060.         if dirs and not dirs[0]:
  1061.             dirs = dirs[1:]
  1062.         
  1063.         
  1064.         try:
  1065.             fw = self.connect_ftp(user, passwd, host, port, dirs)
  1066.             if not file or 'I':
  1067.                 pass
  1068.             type = 'D'
  1069.             for attr in attrs:
  1070.                 (attr, value) = splitvalue(attr)
  1071.                 if attr.lower() == 'type' and value in ('a', 'A', 'i', 'I', 'd', 'D'):
  1072.                     type = value.upper()
  1073.                     continue
  1074.             
  1075.             (fp, retrlen) = fw.retrfile(file, type)
  1076.             headers = ''
  1077.             mtype = mimetypes.guess_type(req.get_full_url())[0]
  1078.             if mtype:
  1079.                 headers += 'Content-type: %s\n' % mtype
  1080.             
  1081.             if retrlen is not None and retrlen >= 0:
  1082.                 headers += 'Content-length: %d\n' % retrlen
  1083.             
  1084.             sf = StringIO(headers)
  1085.             headers = mimetools.Message(sf)
  1086.             return addinfourl(fp, headers, req.get_full_url())
  1087.         except ftplib.all_errors:
  1088.             msg = None
  1089.             raise IOError, ('ftp error', msg), sys.exc_info()[2]
  1090.  
  1091.  
  1092.     
  1093.     def connect_ftp(self, user, passwd, host, port, dirs):
  1094.         fw = ftpwrapper(user, passwd, host, port, dirs)
  1095.         return fw
  1096.  
  1097.  
  1098.  
  1099. class CacheFTPHandler(FTPHandler):
  1100.     
  1101.     def __init__(self):
  1102.         self.cache = { }
  1103.         self.timeout = { }
  1104.         self.soonest = 0
  1105.         self.delay = 60
  1106.         self.max_conns = 16
  1107.  
  1108.     
  1109.     def setTimeout(self, t):
  1110.         self.delay = t
  1111.  
  1112.     
  1113.     def setMaxConns(self, m):
  1114.         self.max_conns = m
  1115.  
  1116.     
  1117.     def connect_ftp(self, user, passwd, host, port, dirs):
  1118.         key = (user, host, port, '/'.join(dirs))
  1119.         if key in self.cache:
  1120.             self.timeout[key] = time.time() + self.delay
  1121.         else:
  1122.             self.cache[key] = ftpwrapper(user, passwd, host, port, dirs)
  1123.             self.timeout[key] = time.time() + self.delay
  1124.         self.check_cache()
  1125.         return self.cache[key]
  1126.  
  1127.     
  1128.     def check_cache(self):
  1129.         t = time.time()
  1130.         if self.soonest <= t:
  1131.             for k, v in self.timeout.items():
  1132.                 if v < t:
  1133.                     self.cache[k].close()
  1134.                     del self.cache[k]
  1135.                     del self.timeout[k]
  1136.                     continue
  1137.             
  1138.         
  1139.         self.soonest = min(self.timeout.values())
  1140.         if len(self.cache) == self.max_conns:
  1141.             for k, v in self.timeout.items():
  1142.                 if v == self.soonest:
  1143.                     del self.cache[k]
  1144.                     del self.timeout[k]
  1145.                     break
  1146.                     continue
  1147.             
  1148.             self.soonest = min(self.timeout.values())
  1149.         
  1150.  
  1151.  
  1152.  
  1153. class GopherHandler(BaseHandler):
  1154.     
  1155.     def gopher_open(self, req):
  1156.         import gopherlib as gopherlib
  1157.         host = req.get_host()
  1158.         if not host:
  1159.             raise GopherError('no host given')
  1160.         
  1161.         host = unquote(host)
  1162.         selector = req.get_selector()
  1163.         (type, selector) = splitgophertype(selector)
  1164.         (selector, query) = splitquery(selector)
  1165.         selector = unquote(selector)
  1166.         if query:
  1167.             query = unquote(query)
  1168.             fp = gopherlib.send_query(selector, query, host)
  1169.         else:
  1170.             fp = gopherlib.send_selector(selector, host)
  1171.         return addinfourl(fp, noheaders(), req.get_full_url())
  1172.  
  1173.  
  1174.